<?php
//dezend by http://www.yunlu99.com/ QQ:270656184
class CI_Hooks
{
	/**
	 * Determines whether hooks are enabled
	 *
	 * @var	bool
	 */
	public $enabled = false;
	/**
	 * List of all hooks set in config/hooks.php
	 *
	 * @var	array
	 */
	public $hooks = array();
	/**
	 * Array with class objects to use hooks methods
	 *
	 * @var array
	 */
	protected $_objects = array();
	/**
	 * In progress flag
	 *
	 * Determines whether hook is in progress, used to prevent infinte loops
	 *
	 * @var	bool
	 */
	protected $_in_progress = false;

	public function __construct()
	{
		$CFG = &load_class('Config', 'core');
		log_message('info', 'Hooks Class Initialized');

		if ($CFG->item('enable_hooks') === false) {
			return NULL;
		}

		if (file_exists(APPPATH . 'config/hooks.php')) {
			include APPPATH . 'config/hooks.php';
		}

		if (file_exists(APPPATH . 'config/' . ENVIRONMENT . '/hooks.php')) {
			include APPPATH . 'config/' . ENVIRONMENT . '/hooks.php';
		}

		if (!isset($hook) || !is_array($hook)) {
			return NULL;
		}

		$this->hooks = &$hook;
		$this->enabled = true;
	}

	public function call_hook($which = '')
	{
		if (!$this->enabled || !isset($this->hooks[$which])) {
			return false;
		}

		if (is_array($this->hooks[$which]) && !isset($this->hooks[$which]['function'])) {
			foreach ($this->hooks[$which] as $val) {
				$this->_run_hook($val);
			}
		}
		else {
			$this->_run_hook($this->hooks[$which]);
		}

		return true;
	}

	protected function _run_hook($data)
	{
		if (is_callable($data)) {
			is_array($data) ? $data[0]->$data[1]() : $data();
			return true;
		}
		else if (!is_array($data)) {
			return false;
		}

		if ($this->_in_progress === true) {
			return NULL;
		}

		if (!(isset($data['filepath']) && isset($data['filename']))) {
			return false;
		}

		$filepath = APPPATH . $data['filepath'] . '/' . $data['filename'];

		if (!file_exists($filepath)) {
			return false;
		}

		$class = (empty($data['class']) ? false : $data['class']);
		$function = (empty($data['function']) ? false : $data['function']);
		$params = (isset($data['params']) ? $data['params'] : '');

		if (empty($function)) {
			return false;
		}

		$this->_in_progress = true;

		if ($class !== false) {
			if (isset($this->_objects[$class])) {
				if (method_exists($this->_objects[$class], $function)) {
					$this->_objects[$class]->$function($params);
				}
				else {
					return $this->_in_progress = false;
				}
			}
			else {
				class_exists($class, false) || require_once $filepath;
				if (!class_exists($class, false) || !method_exists($class, $function)) {
					return $this->_in_progress = false;
				}

				$this->_objects[$class] = new $class();
				$this->_objects[$class]->$function($params);
			}
		}
		else {
			function_exists($function) || require_once $filepath;

			if (!function_exists($function)) {
				return $this->_in_progress = false;
			}

			$function($params);
		}

		$this->_in_progress = false;
		return true;
	}
}

defined('BASEPATH') || exit('No direct script access allowed');

?>
